<?php
/**
 * This file is part of Hyperf.
 *
 * @link     https://www.hyperf.io
 * @document https://doc.hyperf.io
 * @contact  group@hyperf.io
 * @license  https://github.com/hyperf/hyperf/blob/master/LICENSE
 */

namespace Xin\VarDumper\Hyperf;

use Hyperf\Context\ApplicationContext;
use Hyperf\Context\RequestContext;
use Hyperf\Event\Contract\ListenerInterface;
use Hyperf\Framework\Event\AfterWorkerStart;
use Hyperf\HttpServer\Contract\ResponseInterface;
use Symfony\Component\VarDumper\Caster\ReflectionCaster;
use Symfony\Component\VarDumper\Cloner\VarCloner;
use Symfony\Component\VarDumper\Dumper\CliDumper;
use Symfony\Component\VarDumper\Dumper\HtmlDumper;
use Symfony\Component\VarDumper\VarDumper;
use Xin\Support\Arr;

class WorkStartedListener implements ListenerInterface
{
    /**
     * @var VarCloner
     */
    private $cloner;

    /**
     * @var HtmlDumper
     */
    private $htmlDumper;

    /**
     * @var HtmlDumper
     */
    private $cliDumper;

    /**
     * @inerhitDoc
     */
    public function listen(): array
    {
        return [
            AfterWorkerStart::class,
        ];
    }

    /**
     * @inerhitDoc
     */
    public function process(object $event): void
    {
        $this->cloner = new VarCloner();
        $this->cloner->addCasters(ReflectionCaster::UNSET_CLOSURE_FILE_INFO);
        $this->htmlDumper = new HtmlDumper();
        $this->cliDumper = new CliDumper();

        VarDumper::setHandler(function ($var) {
            /** @var \Hyperf\HttpMessage\Server\Request $requestContext */
            $requestContext = RequestContext::getOrNull();
            if ($requestContext && strtolower(Arr::get($requestContext->getSwooleRequest()->header, 'connection')) !== 'upgrade') {
                /** @var ResponseInterface $response */
                $response = ApplicationContext::getContainer()->get(ResponseInterface::class);
                $response->write(self::renderHTML($var) . "\n");
            } else {
                self::renderCLI($var);
            }
        });
    }

    /**
     * @param mixed $var
     * @return string
     */
    public function renderHTML($var): string
    {
        ob_start();
        $this->htmlDumper->dump($this->cloner->cloneVar($var));
        return (string)ob_get_clean();
    }

    /**
     * @param mixed $var
     * @return void
     */
    public function renderCLI($var)
    {
        $this->cliDumper->dump($this->cloner->cloneVar($var));
    }
}
